import { type User } from '@/entity/FrontendStruct';
import { httpUtils as baseHttpUtils } from 'gtl-utils/utils/http-utils';
import { type TreeData } from "../entity/BackendStruct";
import { type Tree } from "../entity/FrontendStruct";

let httpUtils =  {
    request_proxy(url: string, data: RequestInit, invoke?: Function, error?: Function): any{
        baseHttpUtils.request("/api/"+url, data, invoke, error)
    },
    getImage_proxy(url: string, invoke: Function, error?: Function): void{
        baseHttpUtils.getImage("/api/"+url, invoke, error)
    },
    ...baseHttpUtils
}

function parseGetMethodUrl(baseUrl: string, data: FormData | null | undefined){
    if(data == null || data == undefined){
        return baseUrl;
    }
    return baseUrl + getMethodParseFromData(data);
}
function getMethodParseFromData(data: FormData): string{
    let result = '?';
    data.forEach((v,k)=>{
        result+=k+"="+v+"&";
    })
    return result.substring(0, result.length - 1);
}
/** 接口数据结构 */
interface Invoke {
    success?: Function
    fail?: Function
    body?: FormData
}

function basePost(url: string, invoke: Invoke) {
    httpUtils.request_proxy(url, {method: httpUtils.Method.POST, body: invoke.body},  invoke.success, invoke.fail);
}
function baseDelete(url: string, invoke: Invoke){
    httpUtils.request_proxy(parseGetMethodUrl(url, invoke.body), {method: httpUtils.Method.DELETE},  invoke.success, invoke.fail);
}
/** 表单链式编程 */
class GetFormData {
    private data = new FormData()
    static getData() {
        return new GetFormData()
    }
    set(name: string, value: string | Blob) {
        this.data.append(name, value)
        return this;
    }
    setObj(obj: any){
        if (!(obj instanceof Map)){
            obj = new Map(Object.entries(obj));
        }
        (<Map<string, any>>obj).forEach((v,k)=>{
            if( v instanceof Blob){
                this.data.append(k, v);
            }else{
                if( typeof v == 'string' ){
                    this.data.append(k, v);
                }else{
                    this.data.append(k, JSON.stringify(v));
                }
            }
        })
        return this;
    }
    toFormData() {
        return this.data;
    }
}

/** 分页数据结构 */
interface Page extends Invoke {
    page_index: number
    page_size?: number
}

/** 用户登录注销 */
class LoginApi {
    /** 退出登录 */
    logout(invoke: Invoke) {
        httpUtils.request_proxy("logout", { method: httpUtils.Method.GET, }, (data: any) => {
            invoke.success?.(data);
        },
            (error: any) => {
                invoke.fail?.(error)
            }
        )
    }
    /**登录 */
    login(invoke: Invoke) {
        httpUtils.request_proxy("login", {
            method: httpUtils.Method.POST,
            body: invoke.body,
        },
            (data: any) => {
                invoke.success?.(data);
            },
            (err: any) => {
                invoke.fail?.(err);
            }
        )
    }
    /** 获取认证码 */
    flushAuthenticationCode(invoke: Invoke) {
        httpUtils.getImage_proxy("get_img/", (data: Blob) => {
            const objectUrl = URL.createObjectURL(data);
            if (invoke.success != null) {
                invoke.success(objectUrl);
            }
        })
    }
}

/** 组织api */
class ORGApi {
    getOrg(invoke: Invoke) {
        httpUtils.request_proxy("get_org/", { method: httpUtils.Method.GET, body: invoke.body },
            (data: TreeData[]) => {

                let result: Tree[] = []
                let treeMap: Map<number, TreeData> = new Map()
                // 创建Tree 数据结构
                data.forEach((element: TreeData) => {
                    element.index = { id: element.id, label: element.name, children: [] }
                    treeMap.set(element.id, element)
                });
                data.forEach((element: TreeData) => {
                    if (element.pid != null && treeMap.has(element.pid)) {
                        let node = treeMap.get(element.pid)
                        if(element.index != null  ){
                            node?.index?.children?.push(element.index)
                            node?.index?.children?.sort((a,b)=>{
                                return a.label?.localeCompare(b.label) 
                            })
                        }
                    }
                });
                data.forEach((v, key) => {
                    if (!treeMap.has(v.pid)) {
                        if(v.index != null){
                            result.push(v.index)
                        }
                    }
                  });
                result.sort((a:any,b:any)=>{
                    return a.label.localeCompare(b.label) 
                })
                invoke.success?.(result)
            }, (err: any) => {
                invoke.fail?.(err)
            }
        )
    }
    orgAdd(invoke: Invoke){
        basePost('org/add/', invoke)
    }
    orgDel(invoke: Invoke){
        baseDelete('org/del/', invoke)
    }
    orgChangeName(invoke: Invoke){
        basePost("org/change/name/", invoke)
    }
    orgMove(invoke: Invoke){
        basePost("org/move/", invoke)
    }
}

/** 首页api */
class HomeApi {
    getLogins(page: Page) {
        httpUtils.request_proxy("logins/?page_index=" + page.page_index + "&page_size=" + (page.page_size == null ? 10 : page.page_size),
            { method: httpUtils.Method.GET },
            (data: any) => { page.success?.(data) },
            (err: any) => { page.fail?.() }
        )
    }
}

/** 虚拟机api */
class VmboxApi {
    getHosts(invoke: Invoke) {
        httpUtils.request_proxy("virt/domain/hosts/", {
            method: httpUtils.Method.GET,
        }, invoke.success, invoke.fail)
    }
    addDir(invoke: Invoke) {
        httpUtils.request_proxy('virt/domain/add_virt_dirs/', {
            method: httpUtils.Method.POST,
            body: invoke.body
        },
            invoke.success,
            invoke.fail
        )
    }
    delDir(invoke: Invoke) {
        httpUtils.request_proxy("virt/domain/del_virt_dirs/?id=" + invoke.body?.get("id"), {
            method: httpUtils.Method.DELETE
        },
            invoke.success,
            invoke.fail
        )
    }
    getXml(invoke: Invoke) {
        httpUtils.request_proxy("virt/domain/xml/",
            { method: httpUtils.Method.POST, body: invoke.body },
            invoke.success, invoke.fail)
    }
    moveHost(invoke: Invoke) {
        httpUtils.request_proxy("virt/domain/move_host/", {
            method: httpUtils.Method.POST,
            body: invoke.body
        }, invoke.success, invoke.fail)
    }
    start(invoke: Invoke) {
        httpUtils.request_proxy("virt/domain/start/", {
            body: invoke.body,
            method: httpUtils.Method.POST
        },
            invoke?.success,
            invoke.fail
        )
    }
    shutdown(invoke: Invoke) {
        httpUtils.request_proxy("virt/domain/shutdown/", {
            body: invoke.body,
            method: httpUtils.Method.POST
        },
            invoke?.success,
            invoke.fail
        )
    }
    destroy(invoke: Invoke) {
        httpUtils.request_proxy("virt/domain/destroy/", {
            body: invoke.body,
            method: httpUtils.Method.POST
        },
            invoke?.success,
            invoke.fail
        )
    }
}

class UserApi {
    
    userAdd(invoke:  Invoke){
        httpUtils.request_proxy(
        "user/add/", 
        {method: httpUtils.Method.POST, body: invoke.body}, 
        (result: any)=>{invoke.success?.(result);},
         invoke.fail,
        )
    }

    getUser(invoke: Invoke){
        httpUtils.request_proxy(parseGetMethodUrl("userList/", invoke.body), {method: httpUtils.Method.GET}, (result: User[])=>{
            invoke.success?.(result);
        }, invoke.fail)
    }
}

export const formFormat = (obj: Object):FormData=>{
    const result = new FormData();
    if(!(obj instanceof Map)){
        obj= new Map(Object.entries(obj));
    }
    (<Map<string, any>>obj).forEach((v,k)=>{
        v = typeof v == 'string' ? v : JSON.stringify(v);
        result.set(k,v);
    })
    return result;
}
export const getBody = GetFormData.getData;
export const vmboxApi = new VmboxApi();
export const homeApi = new HomeApi();
export const loginApi = new LoginApi();
export const orgApi = new ORGApi();
export const userApi = new UserApi()
